package com.jrx.anytxn.customer.controller;

import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.constant.ErrorMsgConstant;
import com.jrx.anytxn.customer.dto.BaseApiRes;
import com.jrx.anytxn.customer.dto.creditinfo.CreditActiveReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditAdjustReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditAllInfoQueryReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditAllInfoQueryRes;
import com.jrx.anytxn.customer.dto.creditinfo.CreditApprovalReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditCancelReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditFreezeReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditInfoQueryReq;
import com.jrx.anytxn.customer.dto.creditinfo.CreditInfoQueryRes;
import com.jrx.anytxn.customer.dto.customer.CreditReferenceReq;
import com.jrx.anytxn.customer.dto.customer.CreditReferenceRes;
import com.jrx.anytxn.customer.dto.customer.CustomerRenewalReq;
import com.jrx.anytxn.customer.dto.customer.CustomerRenewalRes;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.handel.ICustomerLimitInfoHandler;
import com.jrx.anytxn.customer.service.ICustomerLimitInfoService;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.i18n.response.TxnRespResult;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.redisson.service.RedissonLockService;
import com.jrx.anytxn.redisson.util.LockType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.concurrent.TimeUnit;

/**
 * 客户额度的api接口
 *
 * @author Qingyao Xing
 * @date 2019/7/19 11:20
 */
@Api(tags = "客户额度的api接口")
@RestController
@RequestMapping(value = "/api/customer/limit")
public class CustomerLimitInfoController {
    private static Logger logger = LoggerFactory.getLogger(CustomerLimitInfoController.class);

    @Autowired
    private ICustomerLimitInfoHandler customerLimitInfoHandler;
    @Autowired
    private RedissonLockService redissonLockService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private ICustomerLimitInfoService iCustomerLimitInfoService;

    @ApiOperation(value = "授信添加客户额度请求", notes = "授信添加客户额度请求")
    @PostMapping(value = "/approval")
    public TxnRespResult<BaseApiRes> registerCreditApproval(
            @Valid @RequestBody CreditApprovalReq creditApprovalReq) throws Exception {
        TxnRespResult<BaseApiRes> result = new TxnRespResult<>();
        BaseApiRes baseApiRes = new BaseApiRes();
        baseApiRes.setUserId(creditApprovalReq.getUserId());
        baseApiRes.setSeqNo(creditApprovalReq.getSeqNo());
        result.setData(baseApiRes);
        CmCustomerSecondLevel second = customerService.getSecondLevelByCondition(creditApprovalReq.getUserId(),creditApprovalReq.getChannel(),creditApprovalReq.getTenantId(), null);
        String lockKey = String.format(CustomerConstant.LOAN_REDIS_LOCK, second.getTenantId(),second.getCustomerId());
        logger.info("RedissionLock key:{}", lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(CustomerConstant.LOAN_REDIS_LOCK_WAITE_TIME, CustomerConstant.LOAN_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}", lockKey, lockFlag);
            if (!lockFlag) {
                logger.error(ErrorMsgConstant.LOCK_EXIST);
                throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
            }
            customerLimitInfoHandler.saveCreditApproval(creditApprovalReq);
            result.getSuccess("授信请求成功", baseApiRes);
        } catch (SegmentException e) {
            logger.error(e.getMessage(),e);
            result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(), e.getErrMsg());
        } finally {
            lock.unlock();
        }
        return result;
    }

    @ApiOperation(value = "客户额度查询(按渠道查询)", notes = "客户额度查询(按渠道查询)")
    @PostMapping(value = "/creditInfoQuery")
    public TxnRespResult<CreditInfoQueryRes> getCreditApproval(@Valid @RequestBody CreditInfoQueryReq creditInfoQueryReq) throws TxnException {
        TxnRespResult<CreditInfoQueryRes> result = new TxnRespResult<>();
        return result.getSuccess(customerLimitInfoHandler.getCreditApproval(creditInfoQueryReq));
    }

    @ApiOperation(value = "客户额度树查询", notes = "客户额度树查询")
    @PostMapping(value = "/creditAllInfoQuery")
    public TxnRespResult<CreditAllInfoQueryRes> getCreditApprovalTree(@Valid @RequestBody CreditAllInfoQueryReq creditAllInfoQueryReq) throws TxnException {

        TxnRespResult<CreditAllInfoQueryRes> result = new TxnRespResult<>();
        return result.getSuccess(customerLimitInfoHandler.getAllCreditApproval(creditAllInfoQueryReq));
    }

    @ApiOperation(value = "额度调整", notes = "额度调整")
    @PostMapping(value = "/creditAdjust")
    public TxnRespResult<BaseApiRes> modifyCreditApproval(@Valid @RequestBody CreditAdjustReq creditAdjustReq){
        TxnRespResult<BaseApiRes> result = new TxnRespResult<>();
        BaseApiRes baseApiRes = new BaseApiRes();
        //将请求报文中需要返回属性值放入返回对象中
        baseApiRes.setSeqNo(creditAdjustReq.getSeqNo());
        baseApiRes.setUserId(creditAdjustReq.getUserId());
        try {
             customerLimitInfoHandler.modifyCreditApproval(creditAdjustReq);
             result.getSuccess("额度调整成功",baseApiRes);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(),e.getErrMsg());
        }
        return result;
    }

    @ApiOperation(value = "额度冻结/解冻", notes = "额度冻结/解冻")
    @PostMapping(value = "/creditFreezeRelease")
    public TxnRespResult<BaseApiRes> modifyCreditFreeze(@Valid @RequestBody CreditFreezeReq creditFreezeReq) {
        TxnRespResult<BaseApiRes> result = new TxnRespResult<>();
        BaseApiRes baseApiRes = new BaseApiRes();
        baseApiRes.setUserId(creditFreezeReq.getUserId());
        baseApiRes.setSeqNo(creditFreezeReq.getSeqNo());
        try {
            customerLimitInfoHandler.modifyCreditFreeze(creditFreezeReq);
            result.getSuccess("额度冻结/解冻操作成功",baseApiRes);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.setData(baseApiRes);
            result.getFail(e.getErrCode(), e.getErrMsg());
        }
        return result;
    }

    @ApiOperation(value = "取消授信接口", notes = "取消授信接口")
    @PostMapping(value = "/cancelCredit")
    public TxnRespResult<BaseApiRes> cancelCredit(@Valid @RequestBody CreditCancelReq creditCancelReq) throws Exception {
        TxnRespResult<BaseApiRes> result = new TxnRespResult<>();
        BaseApiRes baseApiRes = new BaseApiRes();
        baseApiRes.setUserId(creditCancelReq.getUserId());
        baseApiRes.setSeqNo(creditCancelReq.getSeqNo());
        String lockKey = String.format(CustomerConstant.LOAN_REDIS_LOCK, creditCancelReq.getTenantId(), creditCancelReq.getUserId(), creditCancelReq.getChannel());
        logger.info("RedissionLock key:{}", lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(CustomerConstant.LOAN_REDIS_LOCK_WAITE_TIME, CustomerConstant.LOAN_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}", lockKey, lockFlag);
            if (!lockFlag) {
                logger.error(ErrorMsgConstant.LOCK_EXIST);
                throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
            }
            customerLimitInfoHandler.cancelCredit(creditCancelReq);
            result.getSuccess("取消授信成功",baseApiRes);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(), e.getErrMsg());
        } finally {
            lock.unlock();
        }
        return result;
    }

    @ApiOperation(value = "额度激活", notes = "额度激活")
    @PostMapping(value = "/creditActive")
    public TxnRespResult<BaseApiRes> creditActive(@Valid @RequestBody CreditActiveReq creditActiveReq) throws Exception {
        TxnRespResult<BaseApiRes> result = new TxnRespResult<>();
        BaseApiRes baseApiRes = new BaseApiRes();
        baseApiRes.setUserId(creditActiveReq.getUserId());
        baseApiRes.setSeqNo(creditActiveReq.getSeqNo());
        String lockKey = String.format(CustomerConstant.LOAN_REDIS_LOCK, creditActiveReq.getTenantId(), creditActiveReq.getUserId(), creditActiveReq.getChannel());
        logger.info("RedissionLock key:{}", lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(CustomerConstant.LOAN_REDIS_LOCK_WAITE_TIME, CustomerConstant.LOAN_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}", lockKey, lockFlag);
            if (!lockFlag) {
                logger.error(ErrorMsgConstant.LOCK_EXIST);
                throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
            }
            customerLimitInfoHandler.creditActive(creditActiveReq);
            result.getSuccess("额度激活成功",baseApiRes);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(), e.getErrMsg());
        } finally {
            lock.unlock();
        }
        return result;
    }


    @ApiOperation(value = "人行征信查询依据实时接口", notes = "人行征信查询依据实时接口")
    @PostMapping(value = "/creditReference")
    public TxnRespResult<CreditReferenceRes> creditReference(@Valid @RequestBody CreditReferenceReq creditReferenceReq){
        TxnRespResult<CreditReferenceRes> result = new TxnRespResult<>();
        try {
            result.getSuccess(customerLimitInfoHandler.creditReference(creditReferenceReq));
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(), e.getErrMsg());
        }
        return result;
    }

    @ApiOperation(value = "客户续场景景判断", notes = "客户续场景景判断")
    @PostMapping(value = "/customerSceneInfo")
    public TxnRespResult<CustomerRenewalRes> customerSceneInfo(@Valid @RequestBody CustomerRenewalReq req) throws Exception {
        TxnRespResult<CustomerRenewalRes> result = new TxnRespResult<>();
        CustomerRenewalRes res = iCustomerLimitInfoService.customerSceneInfo(req);
        result.getSuccess(res);
        return result;
    }

    @ApiOperation(value = "激活时更新授信合同号和额度编号", notes = "激活时更新授信合同号和额度编号")
    @PostMapping(value = "/updateEtlInfos")
    public TxnRespResult<String> updateEtlInfos(@Valid @RequestBody CreditActiveReq req) throws Exception {
        TxnRespResult<String> result = new TxnRespResult<>();
        iCustomerLimitInfoService.updateEtlInfos(req);
        result.getSuccess("success");
        return result;
    }

}
